package com.lion.httpapi.tools;

import java.io.StringReader;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonParser.Feature;
import org.codehaus.jackson.map.ObjectMapper;

/**
 * json处理工具
 * 
 * @author 李永曜
 * @time 2014-7-9下午11:39:13
 * 
 *       jackson 的注解:
 *       <p>
 *       •@JsonIgnoreProperties 此注解是类注解，作用是json序列化时将java
 *       bean中的一些属性忽略掉，序列化和反序列化都受影响。<br/>
 *       •@JsonIgnore此注解用于属性或者方法上（最好是get方法上），作用和上面的@JsonIgnoreProperties一样。<br/>
 *       •@JsonFormat此注解用于属性或者方法上（最好是get方法上），可以方便的把Date类型直接转化为我们想要的模式，比如@JsonFormat
 *       (pattern = "yyyy-MM-dd HH-mm-ss")<br/>
 *       •@JsonSerialize此注解用于属性或者getter方法上，用于在序列化时嵌入我们自定义的代码，
 *       比如序列化一个double时在其后面限制两位小数点。<br/>
 *       </p>
 * @see http://blog.csdn.net/nomousewch/article/details/8955796
 */
public class JsonTools {

	private static final ObjectMapper MAPPER = new ObjectMapper();

	static {
		MAPPER.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, false);
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		MAPPER.getSerializationConfig().withDateFormat(format);
		MAPPER.getDeserializationConfig().withDateFormat(format);
	}

	private static final JsonFactory JSONFACTORY = new JsonFactory();

	public static String beanToJson(Object o) {
		StringWriter sw = new StringWriter(300);
		JsonGenerator jsonGenerator = null;

		try {
			jsonGenerator = JSONFACTORY.createJsonGenerator(sw);
			MAPPER.writeValue(jsonGenerator, o);
			return sw.toString();

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			if (jsonGenerator != null) {
				try {
					jsonGenerator.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	public static <T>T jsonToBean(String json, Class<?> clazz) {
		try {
			return (T) MAPPER.readValue(json, clazz);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public static Map<String, Object> beanToMap(Object o) {
		try {
			return MAPPER.readValue(beanToJson(o), HashMap.class);
		} catch (Exception e) {
			return null;
		}
	}

	@SuppressWarnings("unchecked")
	public static Map<String, Object> jsonToMap(String json,
			boolean collToString) {
		try {
			Map<String, Object> map = MAPPER.readValue(json, HashMap.class);
			if (collToString) {
				for (Map.Entry<String, Object> entry : map.entrySet()) {
					if (entry.getValue() instanceof Collection
							|| entry.getValue() instanceof Map) {
						entry.setValue(beanToJson(entry.getValue()));
					}
				}
			}
			return map;
		} catch (Exception e) {
			return null;
		}
	}

	public static String listToJson(List<Map<String, String>> list) {
		JsonGenerator jsonGenerator = null;
		StringWriter sw = new StringWriter();
		try {
			jsonGenerator = JSONFACTORY.createJsonGenerator(sw);
			new ObjectMapper().writeValue(jsonGenerator, list);
			jsonGenerator.flush();
			return sw.toString();
		} catch (Exception e) {
			return null;
		} finally {
			if (jsonGenerator != null) {
				try {
					jsonGenerator.flush();
					jsonGenerator.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	public static List<Map<String, String>> jsonToList(String json) {
		try {
			if (json != null && !"".equals(json.trim())) {
				JsonParser jsonParse = JSONFACTORY
						.createJsonParser(new StringReader(json));

				ArrayList<Map<String, String>> arrayList = (ArrayList<Map<String, String>>) new ObjectMapper()
						.readValue(jsonParse, ArrayList.class);
				return arrayList;
			} else {
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}